package com.javen.bankpay;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.core.Controller;
import com.jfinal.kit.HttpKit;
import com.jfinal.kit.PropKit;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.Record;


public class PayInterfaceController extends Controller {
	static Log log = Log.getLog(PayInterfaceController.class);
	static PayInterfaceService payInterfaceService = new PayInterfaceService();
	
	private static String domain = PropKit.get("payUrl");// 接口域名
	private static String appId = PropKit.get("payAppId");// 分配的代理商唯一标识
	private static String key = PropKit.get("payKey");

	public Record parseReqToRecord(){
		Record r = new Record();
		Map<String, String[]> map = getParaMap();
		Set<String> set = map.keySet();
		Iterator<String> it = set.iterator();
		while(it.hasNext()){
			String key = it.next();
			if(!key.equals("time")&!key.equals("signature")&&!key.equals("salt")){
				String[] s = map.get(key);
				r.set(key, s[0]);
			}
		}
		return r;
	}
	
	public static void reVerified()
	{
		List<Record> alldebits = payInterfaceService.getAllDebits();
		Iterator<Record> it = alldebits.iterator();
		while(it.hasNext()) {
			Record tmp = it.next();
			String openID = tmp.getStr("openID");
			String id_name = tmp.getStr("id_name");
			String id_no = tmp.getStr("id_no");
			String card_no = tmp.getStr("card_no");
			String bank_phone = tmp.getStr("bank_phone");
			Integer idid = tmp.getInt("id");
			//verifiedInner(openID,id_name,id_no,card_no,bank_phone);
		}
	}
	
	/*
	 * 实名认证 / 绑定借记卡
	 */
	public void verified(){
		String openID = getPara("openID");
		String id_name = getPara("id_name");
		String id_no = getPara("id_no");
		String card_no = getPara("card_no");
		String bank_phone = getPara("bank_phone");
		verifiedInner(openID,id_name,id_no,card_no,bank_phone);
	}
	
	public void verifiedInner(String openID,String id_name ,String id_no,String card_no, String bank_phone)
	{
		String path = "/api/v1.0/debit";
		String nonceStr = System.currentTimeMillis() + getRandomString(8);// 随机字符串
		String customerInfo = DesUtil.encode(card_no + "|" + id_name + "|" + id_no + "|" + bank_phone, key);// 用户信息3des加密
		String provinceCode = "320000";// 省份编码
		String cityCode = "320100";// 城市编码
		String address = "栖霞区甘家边东108号";// 地址
		Double fee0 = 5.2;// 费率
		int d0fee = 100;// 单笔费用
		int pointsType = 0;//0:带积分，1:不带积分

		// 签名map
		Map<String, String> signParams = new HashMap<String, String>();
		signParams.put("appId", appId);
		signParams.put("nonceStr", nonceStr);
		signParams.put("customerInfo", customerInfo);
		signParams.put("provinceCode", provinceCode);
		signParams.put("cityCode", cityCode);
		signParams.put("address", address);
		signParams.put("fee0", fee0.toString());
		signParams.put("d0fee", String.valueOf(d0fee));
		signParams.put("pointsType", String.valueOf(pointsType));

		//签名
		String sign = MerchSdkSign.getSign(signParams, key);

		// 请求参数map
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("appId", appId);
		params.put("sign", sign);
		params.put("nonceStr", nonceStr);
		params.put("customerInfo", customerInfo);
		params.put("provinceCode", provinceCode);
		params.put("cityCode", cityCode);
		params.put("address", address);
		params.put("fee0", fee0);
		params.put("d0fee", d0fee);
		params.put("pointsType", pointsType);

		// 请求头map
		Map<String, String> headers = new HashMap<String, String>();
		headers.put("Content-Type", "application/json");
		log.info(JSONObject.toJSONString(params));

		JSONObject response = JSON.parseObject(HttpKit.post(domain + path, JSONObject.toJSONString(params), headers));
		log.info("绑定借记卡同步返回结果：" + openID + " " + response.toJSONString());
		if(response.getString("isSuccess").equals("true")){
			Record record = new Record();			
			record.set("openID", openID);
			record.set("mchId", response.getString("data"));//商户号
			record.set("card_no", card_no);
			record.set("id_name", id_name);
			record.set("id_no", id_no);
			record.set("bank_phone", bank_phone);
			List<Record> old = payInterfaceService.getDebits(openID);
			if( (old==null) || old.size()==0)
			{
				payInterfaceService.saveDebitCard(record);
			}else
			{
				record.set("id", old.get(0).getInt("id"));
				payInterfaceService.updateDebitCard(record);
			}
			renderJson(new Record().set("result", "success").set("message", response.get("message")));
		}else{
			renderJson(new Record().set("result", "fail").set("message", response.get("message")));
		}
	}

	/*
	 * 查询卡片列表（借记卡debit,信用卡credit)
	 */
	public void getCards(){
		String openID = getPara("openID");
		String cardType = getPara("cardType");
		List<Record> cards; 
		if(cardType.equals("debitCard")){
			cards = payInterfaceService.getCards("debit_card", openID, "");
		}else{
			cards = payInterfaceService.getCards("credit_card", openID, "");
		}
		renderJson(cards);
	}
	
	
	//结算卡修改和费率修改
	public void changeDebit(){
		String path = "/api/v1.0/debit";

		String openID = getPara("openID");
		String card_no = getPara("card_no");// 卡号
		String bank_phone = getPara("bank_phone");// 手机号
		
		Record thisDebitCard = payInterfaceService.getDebits(openID).get(0);
		String id_name = thisDebitCard.getStr("id_name");// 姓名
		String id_no = thisDebitCard.getStr("id_no");// 身份证号

		String nonceStr = System.currentTimeMillis() + getRandomString(8);// 随机字符串
		String customerInfo = DesUtil.encode(card_no + "|" + id_name + "|" + id_no + "|" + bank_phone, key);// 用户信息3des加密
		String merchantFlag = "M02";//修改类型(M02:修改结算卡，M03:修改费率）
		String mchId = thisDebitCard.getStr("mchId");//商户号
		String provinceCode = thisDebitCard.getStr("provinceCode");// 省份编码
		String cityCode = thisDebitCard.getStr("cityCode");// 城市编码
		Double fee0 = thisDebitCard.getDouble("fee0");// 费率
		int d0fee = thisDebitCard.getInt("d0fee");// 单笔费用

		// 签名map
		Map<String, String> signParams = new HashMap<String, String>();
		signParams.put("appId", appId);
		signParams.put("nonceStr", nonceStr);
		signParams.put("customerInfo", customerInfo);
		//signParams.put("merchantFlag", merchantFlag);
		signParams.put("mchId", mchId);
		signParams.put("provinceCode", provinceCode);
		signParams.put("cityCode", cityCode);
		signParams.put("fee0", fee0.toString());
		signParams.put("d0fee", String.valueOf(d0fee));

		//签名
		String sign = MerchSdkSign.getSign(signParams, key);

		// 请求参数map
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("appId", appId);
		params.put("sign", sign);
		params.put("nonceStr", nonceStr);
		params.put("customerInfo", customerInfo);
		//params.put("merchantFlag", merchantFlag);
		params.put("mchId", mchId);
		params.put("provinceCode", provinceCode);
		params.put("cityCode", cityCode);
		params.put("fee0", fee0);
		params.put("d0fee", d0fee);

		log.info(JSONObject.toJSONString(params));
		JSONObject response = JSON.parseObject(sendPut(domain + path, JSONObject.toJSONString(params)));
		log.info("结算卡修改和费率修改同步返回结果：" + response.toJSONString());
		if(response.getString("isSuccess").equals("true")){
			thisDebitCard.set("card_no", card_no);
			thisDebitCard.set("bank_phone", bank_phone);
			thisDebitCard.set("mchId", mchId);
			payInterfaceService.updateDebitCard(thisDebitCard);
			renderJson(new Record().set("result", "success").set("message", "修改成功"));
		}else{
			renderJson(new Record().set("result", "fail").set("message", response.get("message")));
		}
		
	}

	
	/*
	 * 添加信用卡
	 */
	public void addCredit(){
		Record record = parseReqToRecord();
		List<Record> cards = payInterfaceService.getCards("credit_card", record.getStr("openID"), record.getStr("card_no"));
		if(cards.size() > 0){
			renderText("repeat");
		}else{
			payInterfaceService.addCredit(record);
			renderText("success");
		}
	}
	
	public void deleteCredit(){
		Record record = parseReqToRecord();
		payInterfaceService.deleteCredit(record);
		renderText("success");
	}
	

	/*
	 * 交易
	 */
	public void order() {
		String path = "/api/v1.0/preOrder";
		
		String openID = getPara("openID");
		String card_no = getPara("card_no");
		int totalFee = getParaToInt("totalFee");
		Record thisCreditCard = payInterfaceService.getCards("credit_card", openID, card_no).get(0);
		Record thisDebitCard = payInterfaceService.getDebits(openID).get(0);

		String id_name = thisCreditCard.getStr("id_name");// 姓名
		String id_no = thisCreditCard.getStr("id_no");// 身份证号
		String phone = thisCreditCard.getStr("bank_phone");// 手机号

		String nonceStr = System.currentTimeMillis() + getRandomString(12);// 随机字符串
		String customerInfo = DesUtil.encode(card_no + "|" + id_name + "|" + id_no + "|" + phone, key);// 用户信息3des加密
		String agentOrderNo = System.currentTimeMillis() + getRandomString(12);// 代理商订单编号
		String notifyUrl = "http://www.lilishuju.com/llPay/orderNotify";// 订单处理结果通知地址
		String mchId = thisDebitCard.getStr("mchId");// 商户号
		String returnUrl = "http://www.lilishuju.com/front/pos.html";// 订单同步返回地址

		// 签名map
		Map<String, String> signParams = new HashMap<String, String>();
		signParams.put("appId", appId);
		signParams.put("nonceStr", nonceStr);
		signParams.put("customerInfo", customerInfo);
		signParams.put("totalFee", String.valueOf(totalFee));
		signParams.put("agentOrderNo", agentOrderNo);
		signParams.put("notifyUrl", notifyUrl);
		signParams.put("mchId", mchId);
		signParams.put("returnUrl", returnUrl);
		
		//签名
		String sign = MerchSdkSign.getSign(signParams, key);

		// 请求参数map
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("appId", appId);
		params.put("sign", sign);
		params.put("nonceStr", nonceStr);
		params.put("customerInfo", customerInfo);
		params.put("totalFee", String.valueOf(totalFee));
		params.put("agentOrderNo", agentOrderNo);
		params.put("notifyUrl", notifyUrl);
		params.put("mchId", mchId);
		params.put("returnUrl", returnUrl);

		// 请求头map
		Map<String, String> headers = new HashMap<String, String>();
		headers.put("Content-Type", "application/json");
		log.info(JSONObject.toJSONString(params));

		JSONObject response = JSON.parseObject(HttpKit.post(domain + path, JSONObject.toJSONString(params), headers));
		log.info("交易同步返回结果：" + response.toJSONString());
		if(response.getString("isSuccess").equals("true")){
			JSONObject dataObject = JSON.parseObject(response.getString("data"));
			
			Record record = new Record();
			record.set("openID", openID);
			record.set("credit_card_no", card_no);
			record.set("debit_card_no", thisDebitCard.getStr("card_no"));
			record.set("totalFee", totalFee);
			record.set("fee0", thisDebitCard.getDouble("fee0"));
			record.set("agentOrderNo", dataObject.get("agentOrderNo"));
			record.set("orderNo", dataObject.get("orderNo"));
			payInterfaceService.addOrder(record);
			renderJson(new Record().set("isSuccess", "true").set("returnHtml", dataObject.get("returnHtml").toString()));
		}else{
			if(response.getString("message") == null){
				renderJson(new Record().set("result", "fail").set("message", response.get("data")));
			}else{
				renderJson(new Record().set("result", "fail").set("message", response.get("message")));
			}
		}
	}
	
	/*
	 * 订单处理结果通知
	 */
	public void orderNotify(){
		try {
			String requestData = HttpKit.readData(getRequest());
			JSONObject objData = JSONObject.parseObject(requestData);
			String agentOrderNo = objData.getString("agentOrderNo");
			String state = objData.getString("state");//订单状态（0：已下单，1：已受理，2：请求预支付，3：请求失败，4：支付中，5：支付成功，6：支付失败，7：超时关闭）
			// 4 is well done
			
			String settleStatus = "";//结算状态（2：结算成功，4：结算失败，其它）
						
			if(objData.getString("result") != null){
				settleStatus = objData.getString("result");
			}
			
			List<Record> records = payInterfaceService.getOrder(agentOrderNo,"one", "0","10");
			Record record = new Record();
			if(records.size() > 0){
				record = records.get(0);
				if (state.equals("4"))
				{
					record.set("state", "5");
				}else
				{
					record.set("state", "6");
				}
				record.set("settleStatus", settleStatus);
				payInterfaceService.updateOrder(record);
				
				if(state.equals("4"))
				{
				//if(state.equals("5") && settleStatus.equals("0")){//如果支付成功，就需要减小推荐人的费率，推荐的每个人只减一次）
					String openID = record.getStr("openID");
					Record reditRecord = payInterfaceService.getDebits(openID).get(0);
					if(reditRecord.getStr("reduce_fee").equals("0")){
						int totalFee = payInterfaceService.getTotalFee(openID);
						if(totalFee >= 5000){
							reditRecord.set("reduce_fee", "1");
							payInterfaceService.updateDebitCard(reditRecord);
						}
					}
				}
			}
			renderText("success");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void share(){
		String openID = getPara("openID");
		Record parDebit = payInterfaceService.getDebits(openID).get(0);
		String shareResult = "success";
		if(parDebit == null){
			renderText(shareResult);
		}
		if(parDebit.getStr("shareCount").equals("0") && parDebit.getDouble("fee0") > 3.9){
			shareResult = changeDebit(parDebit, parDebit, "share");
		}
		renderText(shareResult);
	}
	
	
	//结算卡修改和费率修改
	public static String changeDebit(Record debit, Record parDebit, String type){
		String path = "/api/v1.0/debit";

		Double newFee = parDebit.getDouble("fee0") - 0.1;
		DecimalFormat df = new DecimalFormat("#.0");
		
		//String openID = getPara("openID");
		String card_no = parDebit.getStr("card_no");// 卡号
		String bank_phone = parDebit.getStr("bank_phone");// 手机号
		
		
		String id_name = parDebit.getStr("id_name");// 姓名
		String id_no = parDebit.getStr("id_no");// 身份证号
		String cityCode = parDebit.getStr("cityCode");// 身份证号
		String provinceCode = parDebit.getStr("provinceCode");// 身份证号
		
		
		
		String nonceStr = System.currentTimeMillis() + getRandomString(8);// 随机字符串
		String merchantFlag = "M03";//修改类型(M02:修改结算卡，M03:修改费率）
		String mchId = parDebit.getStr("mchId");//商户号
		Double fee0 = Double.valueOf(df.format(newFee));// 费率
		int d0fee = 100;// 单笔费用
		String customerInfo = DesUtil.encode(card_no + "|" + id_name + "|" + id_no + "|" + bank_phone, key);// 用户信息3des加密

		// 签名map
		Map<String, String> signParams = new HashMap<String, String>();
		signParams.put("appId", appId);
		signParams.put("nonceStr", nonceStr);
		//signParams.put("merchantFlag", merchantFlag);
		signParams.put("mchId", mchId);
		signParams.put("fee0", fee0.toString());
		signParams.put("d0fee", String.valueOf(d0fee));
		
		signParams.put("customerInfo", customerInfo);
		signParams.put("provinceCode", provinceCode);
		signParams.put("cityCode", cityCode);

		//签名
		String sign = MerchSdkSign.getSign(signParams, key);

		// 请求参数map
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("appId", appId);
		params.put("sign", sign);
		params.put("nonceStr", nonceStr);
		//params.put("merchantFlag", merchantFlag);
		params.put("mchId", mchId);
		params.put("fee0", fee0);
		params.put("d0fee", d0fee);
		params.put("customerInfo", customerInfo);
		params.put("provinceCode", provinceCode);
		params.put("cityCode", cityCode);


		JSONObject response = JSON.parseObject(sendPut(domain + path, JSONObject.toJSONString(params)));
		log.info(JSONObject.toJSONString(params));
		log.info("结算卡修改和费率修改同步返回结果：" + response.toJSONString());
		String result = "";
		if(response.getString("isSuccess").equals("true")){
			log.info("费率更改成功，并更新debit_card---------------");
			if(type.equals("share")){
				parDebit.set("fee0", Double.valueOf(df.format(newFee)));
				parDebit.set("shareCount", "1");
				parDebit.set("mchId", mchId);
				payInterfaceService.updateDebitCard(parDebit);
			}else if(type.equals("change")){
				parDebit.set("fee0", Double.valueOf(df.format(newFee)));
				parDebit.set("d0fee", d0fee);
				parDebit.set("mchId", mchId);
				payInterfaceService.updateDebitCard(parDebit);
			}else{
				parDebit.set("fee0", Double.valueOf(df.format(newFee)));
				payInterfaceService.updateDebitCard(parDebit);
				
				debit.set("reduce_fee", "2");
				debit.remove("parOpenId");
				parDebit.set("mchId", mchId);
				payInterfaceService.updateDebitCard(debit);
			}
			result = "分享成功";
		}else{
			if(response.getString("message") != null){
				result = response.getString("message");
			}else{
				result = "fail";
			}
		}
		return result;
	}
	/*
	 * 统计推荐人
	 */
	/*public void account(){
		String openID = getPara("openID");
		String par_id_name = Db.find("select * from debit_card a left join users b on a.openID = b.parOpenId where b.openId = '"+openID+"' ").get(0).getStr("id_name");
		int count = Db.findFirst("select count(*) as count from users a where a.parOpenId = '"+openID+"' and a.openId <> a.parOpenId").getLong("count").intValue();
		renderJson(new Record().set("name", par_id_name).set("count", count));
	}*/
	
	public void account(){
		String openID = getPara("openID");
		String start = getPara("start");
		String limit = getPara("limit");
		int count = payInterfaceService.getAccount(openID);
		List<Record> list = payInterfaceService.getAccountList(openID, start, limit);
		renderJson(new Record().set("list", list).set("count", count));
	}
	
	/*
	 * 订单记录
	 */
	public void getOrderList(){
		String openID = getPara("openID");
		String start = getPara("start");
		String limit = getPara("limit");
		int count = payInterfaceService.getOrderCount(openID);
		List<Record> list = payInterfaceService.getOrder(openID, "list", start, limit);
		renderJson(new Record().set("list", list).set("count", count));
	}
	
	
	
	/*
	 * 发送http put请求
	 */
	public static String sendPut(String httpUrl, String params) {  
        String result = "";  
        URL url = null;  
        try {  
            url = new URL(httpUrl);  
        } catch (MalformedURLException e) {  
            e.printStackTrace();  
        }  
        if (url != null) {  
            try {  
                HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();  
                urlConn.setRequestProperty("content-type", "application/json");  
                urlConn.setDoInput(true);  
                urlConn.setDoOutput(true);  
                urlConn.setConnectTimeout(5 * 1000);  
                //设置请求方式为 PUT  
                urlConn.setRequestMethod("PUT");  
                  
                urlConn.setRequestProperty("Content-Type", "application/json");  
                urlConn.setRequestProperty("Accept", "application/json");  
                  
                urlConn.setRequestProperty("Charset", "UTF-8");  
                  
      
                DataOutputStream dos = new DataOutputStream(urlConn.getOutputStream());  
                //写入请求参数  
                //这里要注意的是，在构造JSON字符串的时候，实践证明，最好不要使用单引号，而是用“\”进行转义，否则会报错  
                 // 关于这一点在上面给出的参考文章里面有说明  
                dos.writeBytes(params);  
                dos.flush();  
                dos.close();  
                  
                if (urlConn.getResponseCode() == 200) {  
                    InputStreamReader isr = new InputStreamReader(urlConn.getInputStream());  
                    BufferedReader br = new BufferedReader(isr);  
                    String inputLine = null;  
                    while ((inputLine = br.readLine()) != null) {  
                        result += inputLine;  
                    }  
                    isr.close();  
                    urlConn.disconnect();  
                }  
  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
  
        return result;  
  
    }
	/*
	 * 生成随机字符串
	 * length表示生成字符串的长度
	 */
	public static String getRandomString(int length) {
		String base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		Random random = new Random();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < length; i++) {
			int number = random.nextInt(base.length());
			sb.append(base.charAt(number));
		}
		return sb.toString();
	}

}
